%{
import java.io.*;
import java.lang.*;
import java.util.*;
%}

%token	<obj>			ARRAY
%token 	<obj>			BAR
%token  <obj>			BOOLEAN
%token  <obj>			BREAK
%token  <obj>			CASE
%token	<obj>			CHARACTER
%token  <obj>			CONTINUE
%token	<obj>			DO
%token	<obj>			DECIMAL
%token	<obj>			DEFAULT
%token	<obj>			ELSE
%token	<obj>			FOR
%token	<obj>			GRADIENT
%token	<obj>			HIDE
%token	<obj>			INTEGER
%token	<obj>			IF
%token	<obj>			MATRIX
%token	<obj>			PAUSE
%token	<obj>			RETURN
%token	<obj>			SWITCH
%token	<obj>			SHOW
%token	<obj>			STEPALL
%token	<obj>			TIMESTEP
%token	<obj>			VOID
%token	<obj>			WHILE

%token	<obj>			LP
%token	<obj>			RP
%token	<obj>			LCB
%token	<obj>			RCB
%token	<obj>			LSB
%token	<obj>			RSB
%token	<obj>			SEMICOLON
%token	<obj>			COMMA
%token	<obj>			DOT
  
  /* operators */
%token	<obj>			EQ
%token	<obj>			GT
%token	<obj>			LT
%token	<obj>			NOT
%token	<obj>			EQEQ
%token	<obj>			LTE
%token	<obj>			GTE
%token	<obj>			NOTEQ
%token	<obj>			AND
%token	<obj>			OR
%token	<obj>			INCR
%token	<obj>			DECR
%token	<obj>			PLUS
%token	<obj>			MINUS
%token	<obj>			INTO
%token	<obj>			BY
%token	<obj>			MOD
%token	<obj>			PLUSEQ
%token	<obj>			MINUSEQ
%token	<obj>			INTOEQ
%token	<obj>			BYEQ
%token	<obj>			MODEQ

%token	<obj> 	INTCONST
%token	<obj>		DECCONST
%token	<obj>				TRUE
%token	<obj>				FALSE
%token	<obj>				NULL
%token	<obj>		STRINGCONST
%token	<obj>		CHARCONST
%token	<obj>		IDENT
%token  <obj>   SWAP

%type <obj>	program
%type <obj>	definitions
%type <obj>	definition
%type <obj>	function_definition
%type <obj>	function_declarator
%type <obj>	parameter_list
%type <obj>	function_body
%type <obj>	data_definition
%type <obj>	statement_list
%type <obj>	statement
%type <obj>	declaration
%type <obj>	declarator_specifiers
%type <obj>	type_specifiers
%type <obj>	primary_types
%type <obj>	custom_types
%type <obj>	display_specifiers
%type <obj>	declarator_list
%type <obj>	declarator
%type <obj>	only_declarator
%type <obj>	with_definition
%type <obj>	expression
%type <obj>	expression_list
%type <obj>	nonnull_expr_list
%type <obj>	zero_or_single_expression
%type <obj>	single_expression
%type <obj>	primaryexp
%type <obj>	constant
%type <obj>	return_statement
%type <obj>	Row
%type <obj>	Col
%type <obj>	fName
%type <obj>	array_dec
%type <obj>	array_dec_list
%type <obj>	matrix_dec
%type <obj>	const_list


%nonassoc IDENT

%nonassoc	IF
%nonassoc	ELSE

%left		COMMA
%right 	MODEQ BYEQ INTOEQ PLUSEQ MINUSEQ
%right	EQ
%left		OR
%left		AND
%left		EQEQ NOTEQ
%left		LT LTE GT GTE
%left		PLUS MINUS
%left		INTO BY MOD
%right	NEG NOT          /* negation--unary minus */
%left		INCR DECR
%left		LSB RSB LP RP LCB RCB

%%

program :	{ $$ = new AVLNode("import java.io.*;\r\nimport javax.swing.*;\r\n\r\npublic class Output\r\n{\r\n}\r\n"); }
				|	definitions	
					{ 
						$$ = $1;
						((AVLNode)$$).code = "import java.io.*;\r\nimport javax.swing.*;\r\n\r\npublic class Output\r\n{\r\n" + ((AVLNode)$1).code + "}\r\n";
						((AVLNode)$$).tcode = "import java.io.*;\r\nimport javax.swing.*;\r\n\r\npublic class Output\r\n{\r\nstatic AVLGUI gui;\r\n" + ((AVLNode)$1).tcode + "}\r\n";
						Integer ret = avlManager.checkFunction("main", new ArrayList<Integer>());
						if(ret.equals(AVL.INV) == true) {
								System.out.println(fileName+":"+yyline()+": main() function missing.");	
								numErrors++;	
						}
						else if(ret.equals(AVL.VOID) == true) {
								((AVLNode)$$).code = ((String)((AVLNode)$$).code).replace("void main()", "void main(String args[])");
								((AVLNode)$$).tcode = ((String)((AVLNode)$$).tcode).replace("void main()", "void main(String args[])"); 											 											
						}
						else {
							System.out.println(fileName+":"+yyline()+": main() function should have return type void, not "+AVL.getString(ret)+".");	
							numErrors++;
						}
						if(numErrors == 0) { 
							try {
									BufferedWriter out = new BufferedWriter(new FileWriter("Output.java"));
									out.write(((AVLNode)$$).tcode);
									out.close();

							} 
							catch (IOException e) 
							{ 
								System.out.println("Exception ");
							}
							System.out.println("===========================================");
							System.out.println("    "+numErrors+""+ ((numErrors != 1)?" errors":" error ")+"        BUILD SUCCESSFUL");
							System.out.println("===========================================");
						}
						else {
							System.out.println("===========================================");
							System.out.println("    "+numErrors+ " errors        BUILD FAILED");
							System.out.println("===========================================");
							System.out.println("Exiting ...");
						}
					}
				;

definitions	:	definition 
						{
							$$ = $1; 
							((AVLNode)$$).code = ((AVLNode)$1).code; 
							((AVLNode)$$).tcode = ((AVLNode)$1).tcode; 
						}
						|	definitions definition 
							{ 
								String definitions = ((AVLNode)$1).code;
								String definition = ((AVLNode)$2).code;
							 	$$ = $1;	   
								((AVLNode)$$).code =  definitions + definition; 
								((AVLNode)$$).tcode =  ((AVLNode)$1).tcode + ((AVLNode)$2).tcode; 

							}
						;

definition: function_definition 
					{ 
						$$ = $1;
						((AVLNode)$$).tcode = ((AVLNode)$1).tcode; 
						((AVLNode)$$).code = ((AVLNode)$1).code; 
					}
					|	data_definition 
					{ 
						$$ = $1;
						((AVLNode)$$).code = ((AVLNode)$1).code;
						((AVLNode)$$).tcode = ((AVLNode)$1).tcode;  
					}
					;

function_definition	:	type_specifiers function_declarator
										{ 
											String function_declarator_name = ((AVLNode)$2).name;
											Integer type_specifiers_type = ((AVLNode)$1).type;
											ArrayList<Integer> function_declarator_value = (ArrayList<Integer>)((AVLNode)$2).value;

											if(avlManager.addFunction(function_declarator_name, type_specifiers_type, function_declarator_value) == false) {
													System.out.println(fileName+":"+yyline()+": Error at token "+ function_declarator_name + " : Redeclaration.");	
													numErrors++;
											}
										} 
										function_body 
										{
											String type_specifier_code = ((AVLNode)$1).code;
											String function_declarator_code =((AVLNode)$2).code;
											String function_body_code = ((AVLNode)$4).code;
											Integer ret;
											$$ = $1;
											((AVLNode)$$).code = "\r\n\r\npublic static " + type_specifier_code + function_declarator_code + function_body_code;
											((AVLNode)$$).tcode = "\r\n\r\npublic static " + AVL.getRetType(((AVLNode)$1).type) + " " + ((AVLNode)$2).tcode + ((AVLNode)$4).tcode;
											currentFunction = "";
										}
										|	VOID { currentType = "void"; } function_declarator 
										{ 
											String function_declarator_name = ((AVLNode)$3).name;
											ArrayList<Integer> function_declarator_value = (ArrayList<Integer>)((AVLNode)$3).value;
											
											if(avlManager.addFunction(function_declarator_name, AVL.VOID, function_declarator_value) == false) {
												System.out.println(fileName+":"+yyline()+": Error at token "+ function_declarator_value + " : Redeclaration.");	
												numErrors++;
											}
											if(function_declarator_name.equals("main"))
												main = true;
										} function_body 
										{
											String function_declarator_code = ((AVLNode)$3).code; 
											String function_body_code = ((AVLNode)$5).code;
											$$ = $3;
											((AVLNode)$$).code = "\r\n\r\npublic static void "+ function_declarator_code + function_body_code; 
											((AVLNode)$$).tcode = "\r\n\r\npublic static void " + ((AVLNode)$3).tcode + ((AVLNode)$5).tcode;
											currentFunction = "";
										}
										;

function_declarator	:	fName LPar parameter_list RP 
											{ 
												String fName_code = ((AVLNode)$1).code;	
												ArrayList<Integer> parameter_list_value = (ArrayList<Integer>)((AVLNode)$3).value;
												String parameter_list_code = ((AVLNode)$3).code;												
												$$ = $1;
												((AVLNode)$$).name = fName_code;
												((AVLNode)$$).value = parameter_list_value;
												((AVLNode)$$).code = fName_code + "(" + parameter_list_code +")\r\n";
												((AVLNode)$$).tcode = ((AVLNode)$1).tcode + "(" + ((AVLNode)$3).tcode +")\r\n";  
												currentType = "";

											}
										|	fName LPar RP 
											{ 
												String fName_code = ((AVLNode)$1).code;
												$$ = $1;
												((AVLNode)$$).name = fName_code;
												((AVLNode)$$).value = new ArrayList<Integer>();
												((AVLNode)$$).code = fName_code + "()\r\n";
												((AVLNode)$$).tcode = ((AVLNode)$1).tcode + "()\r\n";
												currentType = ""; 

											}
										;

fName	:	IDENT { 
								String currentFunction_code = ((AVLNode)$1).code;		
								currentFunction = currentFunction_code; 
								$$ = $1;
							}
			;

LPar	:	LP { avlManager.push(currentFunction); }
			;

parameter_list	:	type_specifiers IDENT 
								{ 
									String type_specifiers_code = ((AVLNode)$1).code;
									String IDENT_code = ((AVLNode)$2).code;
									Integer type_specifiers_type = ((AVLNode)$1).type;

									$$ = $1;
									((AVLNode)$$).code = type_specifiers_code + " " + IDENT_code; 
									
									
									if(type_specifiers_type == AVL.INTA || 
											type_specifiers_type == AVL.DECA || 
											type_specifiers_type == AVL.CHARA || 
											type_specifiers_type == AVL.BOOLA) {
												((AVLNode)$$).tcode = "AVLArray " + ((AVLNode)$2).tcode;
									} else if(type_specifiers_type == AVL.INTM || 
											type_specifiers_type == AVL.DECM || 
											type_specifiers_type == AVL.CHARM || 
											type_specifiers_type == AVL.BOOLM) {
												((AVLNode)$$).tcode = "AVLMatrix " + ((AVLNode)$2).tcode;
									} else {
												((AVLNode)$$).tcode = ((AVLNode)$1).tcode + " " + ((AVLNode)$2).tcode; 
									}

									if(avlManager.addVariable(IDENT_code, type_specifiers_type) == false) {
										System.out.println(fileName+":"+yyline()+": Error at token "+ type_specifiers_code + " : Redeclaration.");	
										numErrors++;
									}								

									if(((AVLNode)$$).value == null ) {
										((AVLNode)$$).value = (Object) new ArrayList<Integer>();
									}
									((ArrayList<Integer>)((AVLNode)$$).value).add(type_specifiers_type);

									currentType = "";

								}
								|	parameter_list COMMA type_specifiers IDENT 
								{ 
									String parameter_list_code = ((AVLNode)$1).code;
									String type_specifiers_code = ((AVLNode)$3).code;
									String IDENT_code = ((AVLNode)$4).code;
									Integer type_specifiers_type = ((AVLNode)$3).type;
									Integer IDENT_type = ((AVLNode)$4).type;

									$$ = $1;
									((AVLNode)$$).code =  parameter_list_code + ", " + type_specifiers_code + IDENT_code; 
									((AVLNode)$$).tcode =  ((AVLNode)$1).tcode + ", " + ((AVLNode)$3).tcode + ((AVLNode)$4).tcode; 

									if(avlManager.addVariable(IDENT_code, type_specifiers_type) == false) {
										System.out.println(fileName+":"+yyline()+": Error at token "+ parameter_list_code + " : Redeclaration.");	
										numErrors++;
									}								

									((ArrayList<Integer>)((AVLNode)$$).value).add(type_specifiers_type);
							
									currentType = "";

								}
								;

function_body	:	LCB statement_list return_statement RCurly 
							{ 					
								$$ = $3;
								((AVLNode)$$).code = "{\r\n" + ((AVLNode)$2).code + ((AVLNode)$3).code + "}\r\n";
								
								if(main) {
									((AVLNode)$$).tcode = "{\r\ngui = new AVLGUI(\"" + fileName + "\");\r\n" + ((AVLNode)$2).tcode + ((AVLNode)$3).tcode + "}\r\n";
									main = false;
								} else {
									((AVLNode)$$).tcode = "{\r\n" + ((AVLNode)$2).tcode + ((AVLNode)$3).tcode + "}\r\n"; 
								}  			

							}
							| LCB statement_list RCurly 
							{ 
								String statement_list_code = ((AVLNode)$2).code; 
								$$ = $2;
								((AVLNode)$$).code = "{\r\n" + statement_list_code +"}\r\n";
								if(main) {
									((AVLNode)$$).tcode = "{\r\ngui = new AVLGUI(\"test.src\");\r\n" + statement_list_code +"}\r\n";
									main = false;
								} else {
									((AVLNode)$$).tcode = "{\r\n" + statement_list_code +"}\r\n";
								}
								System.out.println(fileName+":"+yyline()+":"+" Error : missing return statement for "+currentFunction+".");
								numErrors++;
							}
							|	LCB return_statement RCurly 
							{ 								
								String return_statement_code = ((AVLNode)$2).code;
								$$ = $2;
								((AVLNode)$$).code = "{\r\n" + return_statement_code + "}\r\n"; 
								((AVLNode)$$).tcode = "{\r\n" + ((AVLNode)$2).tcode + "}\r\n"; 

							}
							| LCB RCurly 
							{ 
								$$ = new AVLNode("{\r\n"+"}\r\n"); 
								System.out.println(fileName+":"+yyline()+":"+" Error : missing return statement for "+currentFunction+".");
								numErrors++;
							}
							;

LCurly	:	LCB	
				{ 
					if(!array && !matrix) {
						avlManager.push(); 
					}
					else if(matrix) {
						if(countRows == 1)
							;
						countRows++;
						if(countRows > numRows)
							System.out.println(fileName+":"+yyline()+": Error : Too many elements in matrix.");
						if(numColumns != countRowElements)
							System.out.println(fileName+":"+yyline()+": Error : Too few columns in matrix.");
						countRowElements = 0;
					}
				}
				;

RCurly	:	RCB 
				{ 
						avlManager.pop(); 
				}
				;

return_statement	:	RETURN SEMICOLON	
									{ 
										$$ = new AVLNode("return;\r\n");	
										Integer retType = avlManager.getFunctionReturnType(currentFunction);
										if(!retType.equals(AVL.VOID)) {
											System.out.println(fileName+":"+yyline()+" Error in return statement. Function "+currentFunction+" expects return type void.");
											numErrors++;
										}
										((AVLNode)$$).tcode = "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\n";
										((AVLNode)$$).tcode += "return;\r\n";
									}
									|	RETURN single_expression SEMICOLON	
									{ 
										String single_expression_code = ((AVLNode)$2).code;
										Integer single_expression_type = ((AVLNode)$2).type;
														
										$$ = $2; 
										((AVLNode)$$).code = "return " + single_expression_code + ";\r\n";

										((AVLNode)$$).tcode = "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\nreturn " + AVL.getCast(single_expression_type) + single_expression_code + ".get();\r\n";
										Integer rType  = avlManager.getFunctionReturnType(currentFunction);
										if(! rType.equals(single_expression_type)) {
											System.out.println(fileName+":"+yyline()+" Error in return statement. Function "+currentFunction+" expects return type "+AVL.getString(rType)+".");
											numErrors++;
										}
										

									}
									;

data_definition	:	declarator_specifiers declarator_list SEMICOLON 
								{ 
									$$ = $1;
									((AVLNode)$$).code = ((AVLNode)$1).code + ((AVLNode)$2).code + ";\r\n"; 
									((AVLNode)$$).tcode = ((AVLNode)$1).tcode + ((AVLNode)$2).tcode + ";\r\n"; 
									currentType = ""; 
									array = false;
									matrix = false;
									numColumns = 0;
									numRows = 0;
									countElements = 0;
									countRowElements = 0;
									countRows = 0;
						
									ArrayList<String> names = (ArrayList<String>)((AVLNode)$2).value;

									if(((AVLNode)$2).type.equals(AVL.INV) || ((AVLNode)$2).type.equals(((AVLNode)$1).type)) {

										for(String s : names) {
											if(avlManager.addVariable(s, ((AVLNode)$1).type) == false) {
												System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$2).code + " : Redeclaration.");
												numErrors++;
											}
										}
									}
									else {
										System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$2).code + " : Type mismatch in assignment.");
										numErrors++;
									}	
									((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\n";

								}
								;

statement_list	:	statement { $$ = $1; }
								|	statement_list statement 
									{ 
										String statement_list_code = ((AVLNode)$1).code, statement_code = ((AVLNode)$2).code;												
										$$ = $1; 
										((AVLNode)$$).code = statement_list_code + statement_code; 
										((AVLNode)$$).tcode = ((AVLNode)$1).tcode + ((AVLNode)$2).tcode; 

									}
								;

statement :	declaration	
					{ 
						$$ = $1;
						currentType = ""; 

					}
					|	single_expression SEMICOLON 
					{ 
						String expression_code = ((AVLNode)$1).code;						
						$$ = $1;
						((AVLNode)$$).code = expression_code + ";\r\n"; 
						((AVLNode)$$).tcode = ((AVLNode)$1).tcode + ";\r\n"; 
						currentType = "";
						callList.clear(); 
						((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\n";
					}
					| LCurly statement_list RCurly 
					{ 
						$$ = $2; 
						((AVLNode)$$).code = "{\r\n" + ((AVLNode)$2).code + "}\r\n"; 
						((AVLNode)$$).tcode = "{\r\n" + ((AVLNode)$2).tcode + "}\r\n"; 
					}
					|	LCurly RCurly { $$ = new AVLNode("{\r\n}\r\n"); }
					|	IF LP single_expression RP statement ELSE statement 
					{
						String single_expression_code = ((AVLNode)$3).code;
						String statement1_code = ((AVLNode)$5).code;
						String statement2_code = ((AVLNode)$7).code;	
								
						$$ = $3;
						((AVLNode)$$).code = "if("+ single_expression_code +")\r\n" + statement1_code + "else\r\n" + statement2_code; 
						((AVLNode)$$).tcode = "if("+ ((AVLNode)$3).tcode +")\r\n" + ((AVLNode)$5).tcode + "else\r\n" + ((AVLNode)$7).tcode;
						/* Check if $3 is a bool exp */

						Integer single_expression_type = ((AVLNode)$3).type;

						if(!single_expression_type.equals(AVL.BOOL)) {
							System.out.println(fileName+":"+((AVLNode)$1).line+": Error at token "+ single_expression_code + " : expected boolean expression in if statement.");
							numErrors++;
						}
					}
					|	IF LP single_expression RP statement 
					{ 
						String single_expression_code = ((AVLNode)$3).code;
						String statement_code = ((AVLNode)$5).code;
						Integer single_expression_type = ((AVLNode)$3).type;

						$$ = $3; 
						((AVLNode)$$).code = "if("+ single_expression_code + ")\r\n" + statement_code;
						((AVLNode)$$).tcode = "if("+ "gui.controlledEvaluation(" + ((AVLNode)$3).tcode + ", " + ((AVLNode)$1).line + "))\r\n" + ((AVLNode)$5).tcode;
 
						if(!single_expression_type.equals(AVL.BOOL)) {
							System.out.println(fileName+":"+((AVLNode)$1).line+": Error at token "+ single_expression_code + " : expected boolean expression in if statement.");
							numErrors++;
						}

					}

					|	WHILE LP single_expression RP statement 
					{ 
						String statement_code = ((AVLNode)$5).code;
						String statement_code1 = ((AVLNode)$5).tcode;
						String single_expression_code = ((AVLNode)$3).code;
						String single_expression_code1 = ",gui.highlightSourceLine(" + ((AVLNode)$3).tcode + ", " + ((AVLNode)$1).line + ")";
						Integer single_expression_type = ((AVLNode)$3).type;						

						$$ = $5;
						((AVLNode)$$).code = "while("+ single_expression_code +")\r\n" + statement_code; /* Check $3 == boolean type */
						((AVLNode)$$).tcode = "while("+ single_expression_code1 +")\r\n" + statement_code1;
						if(!single_expression_type.equals(AVL.BOOL)) {
							System.out.println(fileName+":"+yyline()+": Error at token "+ single_expression_code + " : expected boolean expression in while statement.");
							numErrors++;
						}

					}
					|	DO LCurly statement_list RCurly WHILE LP single_expression RP SEMICOLON 
					{
						String single_expression_code = ((AVLNode)$7).code;
						String single_expression_code1 = ((AVLNode)$7).tcode;
						String statement_list_code = ((AVLNode)$3).code;
						String statement_list_code1 = ",gui.highlightSourceLine(" +((AVLNode)$3).tcode + ", " + ((AVLNode)$1).line + ")";		
						Integer single_expression_type = ((AVLNode)$7).type;
							
						$$ = $3; 
						((AVLNode)$$).code = "do\r\n{\r\n"+ statement_list_code +"}while(" + single_expression_code + ");\r\n"; /* Check $7 == boolean type */
						((AVLNode)$$).tcode = "do\r\n{\r\n"+ statement_list_code1 +"}while(" + single_expression_code1 + ");\r\n"; 
						if(!single_expression_type.equals(AVL.BOOL)) {
							System.out.println(fileName+":"+yyline()+": Error at token "+ single_expression_code + " : expected boolean expression in do while statement.");
							numErrors++;
						}
						((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+((AVLNode)$1).line+");\r\ngui.block();\r\n\r\n";
					}
					|	FOR LP expression_list SEMICOLON zero_or_single_expression SEMICOLON expression_list RP statement 
					{
						String expression_list1_code = ((AVLNode)$3).code;
						String expression_list1_code1 = ((AVLNode)$3).tcode;
						String zero_or_single_expression_code = ((AVLNode)$5).code;
						String zero_or_single_expression_code1 = "gui.controlledEvaluation("+((AVLNode)$5).tcode + ", " + ((AVLNode)$1).line + ")";
						Integer zero_or_single_expression_type = ((AVLNode)$5).type;
						String expression_list2_code = ((AVLNode)$7).code;
						String expression_list2_code1 = ((AVLNode)$7).tcode;
	 					String statement_code = ((AVLNode)$9).code;
	 					String statement_code1 = ((AVLNode)$9).tcode;
						String gui_code = ",gui.highlightSourceLine("+ ((AVLNode)$1).line +"), gui.block()";

						$$ = $9; 
						((AVLNode)$$).code = "for("+ expression_list1_code + ";" + zero_or_single_expression_code + ";" + expression_list2_code + ")\r\n" + statement_code; 
						((AVLNode)$$).tcode = "for("+ expression_list1_code1 + gui_code + ";" + zero_or_single_expression_code1 +";" + expression_list2_code1 + gui_code+")\r\n" + statement_code1; 
						/* Check $5 == boolean type */
						if(!zero_or_single_expression_type.equals(AVL.BOOL)) {
							System.out.println(fileName+":"+yyline()+": Error at token "+ zero_or_single_expression_code + " : expected boolean expression in for statement.");
							numErrors++;
						}

					}
					|	BREAK SEMICOLON { $$ = new AVLNode("break;\r\n"); ((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\n";}
					|	CONTINUE SEMICOLON { $$ = new AVLNode("continue;\r\n"); ((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\n";}
					|	PAUSE SEMICOLON { $$ = new AVLNode("pause;\r\n"); ((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\ngui.pause();\r\n\r\n";}
					|	GRADIENT expression SEMICOLON 
					{ 
						String expression_code = ((AVLNode)$2).code;
						String expression_code1 = ((AVLNode)$2).tcode;
						$$ = $2;
						((AVLNode)$$).code = "gradient " + expression_code + ";\r\n"; 
						((AVLNode)$$).tcode = "gradient " + expression_code1 + ";\r\n"; 
						((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\n";
					}
					| SHOW IDENT SEMICOLON 
					{ 
						String IDENT_code = ((AVLNode)$2).code;
						String IDENT_code1 = ((AVLNode)$2).tcode;
						if(avlManager.checkVariable(IDENT_code) == AVL.INV) {
							System.out.println(fileName+":"+yyline()+": Error at token "+ IDENT_code + " : not declared.");
							numErrors++;
						}
						$$ = $2;
						((AVLNode)$$).code = "show " + IDENT_code + ";\r\n"; 
						((AVLNode)$$).tcode = "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\ngui.watch("+IDENT_code+");\r\n\r\n";
					}
					|	HIDE IDENT SEMICOLON 
					{ 
						String IDENT_code = ((AVLNode)$2).code;
						String IDENT_code1 = ((AVLNode)$2).tcode;
						if(avlManager.checkVariable(IDENT_code) == AVL.INV) {
							System.out.println(fileName+":"+yyline()+": Error at token "+ IDENT_code + " : not declared.");
							numErrors++;
						}
						$$ = $2;
						((AVLNode)$$).code = "hide " + IDENT_code + ";\r\n";
						((AVLNode)$$).tcode = "hide " + IDENT_code1 + ";\r\n";
						((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\n";
					}
					|	SEMICOLON { $$ = new AVLNode(";\r\n"); }
					;

declaration	:	declarator_specifiers declarator_list SEMICOLON 
						{ 
							$$ = $1;
							((AVLNode)$$).code = ((AVLNode)$1).code + ((AVLNode)$2).code + ";\r\n"; 
							((AVLNode)$$).tcode = ((AVLNode)$1).tcode + ((AVLNode)$2).tcode + ";\r\n"; 
							if(((AVLNode)$1).type == AVL.INTA || ((AVLNode)$1).type == AVL.DECA || ((AVLNode)$1).type == AVL.CHARA || ((AVLNode)$1).type == AVL.BOOLA) {
								((AVLNode)$$).tcode += "AVLArray " + ((AVLNode)$2).name + " = new AVLArray(\"" + ((AVLNode)$2).name + "\", " + ((AVLNode)$2).name + "_);\r\n\r\n";
						//		((AVLNode)$2).name+="_";
							} else if (((AVLNode)$1).type == AVL.INTM || ((AVLNode)$1).type == AVL.DECM || ((AVLNode)$1).type == AVL.CHARM || ((AVLNode)$1).type == AVL.BOOLM) {
								((AVLNode)$$).tcode += "AVLMatrix " + ((AVLNode)$2).name + " = new AVLMatrix(\"" + ((AVLNode)$2).name + "\", " + ((AVLNode)$2).name + "_);\r\n\r\n";
							}
							
							((AVLNode)$$).tcode += "\r\ngui.highlightSourceLine("+yyline()+");\r\ngui.block();\r\n\r\n";
							currentType = ""; 
							array = false;
							matrix = false;
							numColumns = 0;
							numRows = 0;
							countElements = 0;
							countRowElements = 0;
							countRows = 0;
							index = 0;
						
							ArrayList<String> names = (ArrayList<String>)((AVLNode)$2).value;
							if(((AVLNode)$2).type.equals(AVL.INV) || ((AVLNode)$2).type.equals(((AVLNode)$1).type)) {
								for(String s : names) {								
									if(showFlag) {
										((AVLNode)$$).tcode += "gui.watch("+s+");\r\n";
									}

									if(avlManager.addVariable(s, ((AVLNode)$1).type) == false) {
										System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$2).code + " : Redeclaration.");
										numErrors++;
									}
								}
								showFlag = false;
							}
							else {
								System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$2).code + " : Type mismatch in assignment.");
								numErrors++;
							}	

						}
						;

declarator_specifiers	:	type_specifiers { $$ = $1; }
											|	display_specifiers type_specifiers 
											{ 
												$$ = $2;
												((AVLNode)$$).code = ((AVLNode)$1).code + " " + ((AVLNode)$2).code; 
												((AVLNode)$$).tcode = ((AVLNode)$1).tcode + " " + ((AVLNode)$2).tcode; 

											}
											;
												
type_specifiers	:	primary_types { $$ = $1; }
								| custom_types { $$ = $1; }
								;

primary_types	:	INTEGER { $$ = new AVLNode("AVLBasicType "); ((AVLNode)$$).code = "int "; ((AVLNode)$$).type = AVL.INT; }
							| DECIMAL { $$ = new AVLNode("AVLBasicType "); ((AVLNode)$$).code = "double "; ((AVLNode)$$).type = AVL.DEC; }
							| CHARACTER { $$ = new AVLNode("AVLBasicType "); ((AVLNode)$$).code = "char "; ((AVLNode)$$).type = AVL.CHAR; }
							| BOOLEAN { $$ = new AVLNode("AVLBasicType "); ((AVLNode)$$).code = "boolean "; ((AVLNode)$$).type = AVL.BOOL; }
							;

custom_types	:	ARRAY LT primary_types GT 
							{ 
								$$ = $3;
								((AVLNode)$$).code = ((AVLNode)$3).code + "[] ";
								((AVLNode)$$).tcode = "AVLBasicType[] ";
								((AVLNode)$$).type = (Integer)(((AVLNode)$$).type.intValue() + 1);
								currentType += " array"; 
								array = true; 

							}
							|	MATRIX LT primary_types GT 
							{ 
								$$ = $3; 
								((AVLNode)$$).code = ((AVLNode)$3).code+"[][] ";
								((AVLNode)$$).tcode = "AVLBasicType[][] ";
								((AVLNode)$$).type = (Integer)(((AVLNode)$$).type.intValue() + 2);
								currentType += " matrix"; 
								matrix = true;

							}
							;
				
display_specifiers	:	SHOW { $$ = new AVLNode(""); showFlag = true; }
										|	HIDE { $$ = new AVLNode(""); showFlag = false; }
										;

declarator_list :	declarator 
								{ 
									$$ = $1; 

									if( ((AVLNode)$$).value == null ) {
										((AVLNode)$$).value = (Object) new ArrayList<String>();
										((ArrayList<String>)((AVLNode)$$).value).clear();
									}
									((ArrayList<String>)((AVLNode)$$).value).add(((AVLNode)$1).name);
								}
								|	declarator_list COMMA declarator 
								{ 
									$$ = $1;
									((AVLNode)$$).code = ((AVLNode)$1).code + "," + ((AVLNode)$3).code; 
									((AVLNode)$$).tcode = ((AVLNode)$1).tcode + "," + ((AVLNode)$3).tcode; 
									((ArrayList<String>)((AVLNode)$$).value).add(((AVLNode)$3).name);
								}
								;

declarator	: only_declarator
						{	
							$$ = $1;

							if(((AVLNode)$1).code.contains("[")) {
									((AVLNode)$$).tcode = ((AVLNode)$1).name + "_ = new AVLBasicType(\""+((AVLNode)$1).name+"\", 0)";
							} else {
								((AVLNode)$$).tcode = ((AVLNode)$1).name + " = new AVLBasicType(\""+((AVLNode)$1).name+"\", 0)";
							}
							((AVLNode)$$).name = ((AVLNode)$1).name;
						}
						|	only_declarator EQ with_definition
						{
							$$ = $1;
							if(((AVLNode)$3).type == AVL.INTA || ((AVLNode)$3).type == AVL.DECA || ((AVLNode)$3).type == AVL.CHARA || ((AVLNode)$3).type == AVL.BOOLA || ((AVLNode)$3).type == AVL.INTM || ((AVLNode)$3).type == AVL.DECM || ((AVLNode)$3).type == AVL.CHARM || ((AVLNode)$3).type == AVL.BOOLM) {
								((AVLNode)$$).tcode = ((AVLNode)$$).name + "_ = "+((AVLNode)$3).tcode;
							} else {
								((AVLNode)$$).tcode = ((AVLNode)$$).name + " = "+((AVLNode)$3).tcode;
							}
							((AVLNode)$$).code = ((AVLNode)$$).name + " = " + ((AVLNode)$3).code;
							((AVLNode)$$).name = ((AVLNode)$1).name;
							((AVLNode)$$).type = ((AVLNode)$3).type;

							if(((AVLNode)$1).row == 0 && ((AVLNode)$1).col != 0) {
								if(((AVLNode)$3).col < ((AVLNode)$1).col) {
									System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Too few elements in the array.");
									numErrors++;
								}
								else if(((AVLNode)$3).col > ((AVLNode)$1).col) {
									System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Too many elements in the array.");
									numErrors++;
								}
							}
							else if(((AVLNode)$1).row != 0 && ((AVLNode)$1).col != 0) {
								if(((AVLNode)$3).col < ((AVLNode)$1).col) {
									System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Too few elements in the matrix row.");
									numErrors++;
								}
								else if(((AVLNode)$3).col > ((AVLNode)$1).col) {
									System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Too many elements in the matrix row.");
									numErrors++;
								}
								if(((AVLNode)$3).row < ((AVLNode)$1).row) {
									System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Too few matrix rows.");
									numErrors++;
								}
								else if(((AVLNode)$3).row > ((AVLNode)$1).row) {
									System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Too many matrix rows.");
									numErrors++;
								}
							}
						}
						;

with_definition	:	single_expression
								{ 
									$$ = $1;
									((AVLNode)$$).tcode = "new AVLBasicType(\"" + index + "\", "+ ((AVLNode)$1).tcode + ")";  
									index++;
								}
								| array_dec
								{
									$$ = $1;
								}
								| matrix_dec
								{
									$$ = $1;
								}
								;

array_dec	:	LCB const_list RCB
						{
							$$ = $2;
							((AVLNode)$$).code = "{ " + ((AVLNode)$2).code + " }"; 
							((AVLNode)$$).tcode = "{ " + ((AVLNode)$2).tcode + " }"; 
							((AVLNode)$$).type += 1;
						}
						;

const_list	:	constant { $$ = $1; 
												((AVLNode)$$).tcode = "new AVLBasicType(\"" + index + "\", "+ ((AVLNode)$1).tcode + ")";  
												index++; 
												((AVLNode)$$).col++; }
						| const_list COMMA constant
						{
							$$ = $1;
							((AVLNode)$$).code = ((AVLNode)$1).code + ", " + ((AVLNode)$3).code ;
							((AVLNode)$$).tcode = ((AVLNode)$1).tcode + ", " + "new AVLBasicType(\"" + index + "\", "+ ((AVLNode)$3).tcode + ")";
							index++;
							if(!((AVLNode)$1).type.equals(((AVLNode)$3).type)) {
								System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Types are not uniform in list.");
								numErrors++;
							}
							((AVLNode)$$).col++;
						}
						;

matrix_dec	:	LCB array_dec_list RCB
						{
							$$ = $2;
							((AVLNode)$$).code = "{ " + ((AVLNode)$2).code + " }";
							((AVLNode)$$).tcode = "{ " + ((AVLNode)$2).tcode + " }";
							((AVLNode)$$).type += 1;
						}
						;	

array_dec_list	:	array_dec
								{
									$$ = $1;
								  ((AVLNode)$$).row++;
								}
								| array_dec_list COMMA array_dec
								{
									$$ = $1;
									((AVLNode)$$).code = ((AVLNode)$1).code + ", " + ((AVLNode)$3).code;	
									((AVLNode)$$).tcode = ((AVLNode)$1).tcode + ", " + ((AVLNode)$3).tcode;	
									if(!((AVLNode)$1).type.equals(((AVLNode)$$).type)) {
										System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Types are not uniform in list.");
										numErrors++;
									}
									((AVLNode)$$).row++;
								}
								;


only_declarator	:	IDENT 
								{
									String ident = ((AVLNode)$1).code;
									$$ = $1; 
									((AVLNode)$$).name = ident;
								}
								|	IDENT LSB Row RSB 
								{ 
									String ident = ((AVLNode)$1).code, index = ((AVLNode)$3).code;
									$$ = $1;
									((AVLNode)$$).name = ident;
									((AVLNode)$$).code = ident + "[" + index + "]"; 
									((AVLNode)$$).tcode = ident;

									((AVLNode)$$).row = 0;
									((AVLNode)$$).col = Integer.parseInt(((AVLNode)$3).code);
									((AVLNode)$$).size = Integer.parseInt(((AVLNode)$3).code);

									if(((AVLNode)$$).col <= 0) {
										System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Invalid size of array.");
										numErrors++;
									}

								}
								|	IDENT LSB Row RSB LSB Col RSB 
								{ 
									String ident = ((AVLNode)$1).code, Row = ((AVLNode)$3).code, Col = ((AVLNode)$6).code;
									$$ = $1;
									((AVLNode)$$).name = ident;
									((AVLNode)$$).code = ident + "[" + Row + "][" + Col + "]";
									((AVLNode)$$).tcode = ident;

									if( ((AVLNode)$$).value == null ) {
										((AVLNode)$$).value = (Object) new ArrayList<String>();
									}

									((AVLNode)$$).size = Integer.parseInt(Row) * Integer.parseInt(Col);
									((AVLNode)$$).row = Integer.parseInt(Row);
									((AVLNode)$$).col = Integer.parseInt(Col);

									if(((AVLNode)$$).row <= 0 || ((AVLNode)$$).col <= 0) {
										System.out.println(fileName+":"+yyline()+": Error at token "+ ((AVLNode)$1).code + " : Invalid size of matrix.");
										numErrors++;
									}
								}
								;

Row	:	INTCONST 
		{
			if(array) {
				numElements = Integer.parseInt(((AVLNode)$1).code);
				countElements = 0;
			}
			else if(matrix) {
				numRows = Integer.parseInt(((AVLNode)$1).code);
			}
			$$ = $1;
			((AVLNode)$$).type = AVL.INT;

		}
		;

Col	:	INTCONST 
		{
			if(matrix) {
				numColumns = Integer.parseInt(((AVLNode)$1).code);
			}
			$$ = $1;
			((AVLNode)$$).type = AVL.INT;

		}
		;

expression	:	nonnull_expr_list { $$ = $1; }
						;

expression_list	:	
								{ 
									$$ = new AVLNode(""); 
									((AVLNode)$$).value = (Object)new ArrayList<Integer>(); 

								}
								| nonnull_expr_list 
								{ 
									$$ = $1; 
									((AVLNode)$$).type = AVL.LIST; 

								}
								;

nonnull_expr_list	:	single_expression 
									{ 
										$$ = $1;
										if ( ((AVLNode)$$).value == null )	{
											((AVLNode)$$).value = (Object) new ArrayList<Integer>();
										}
										((ArrayList<Integer>)((AVLNode)$1).value).add(((AVLNode)$1).type);
				
										if(paramStart) {
											if(((AVLNode)$1).type != AVL.INTA	&& 
													((AVLNode)$1).type != AVL.CHARA	&& 
													((AVLNode)$1).type != AVL.DECA	&& 
													((AVLNode)$1).type != AVL.BOOLA	&& 
													((AVLNode)$1).type != AVL.INTM	&& 
													((AVLNode)$1).type != AVL.CHARM	&& 
													((AVLNode)$1).type != AVL.DECM  && 
													((AVLNode)$1).type != AVL.BOOLM) { 
														((AVLNode)$$).tcode = "new AVLBasicType(\"1\", " + ((AVLNode)$1).tcode + ")";
											}
										}

										((AVLNode)$$).type = AVL.LIST;
									}
									| nonnull_expr_list COMMA single_expression 
									{
										String n_exp_list = ((AVLNode)$1).code, s_exp = ((AVLNode)$3).code;
										String n_exp_list1 = ((AVLNode)$1).tcode, s_exp1 = ((AVLNode)$3).tcode;
										Integer s_exp_type = ((AVLNode)$3).type;
										
										$$ = $1;
										((AVLNode)$$).code =  n_exp_list + ", " + s_exp; 

										if ( ((AVLNode)$$).value != null )	{
											((ArrayList<Integer>)((AVLNode)$$).value).add(s_exp_type);
										}

										if(paramStart) {
											if(((AVLNode)$3).type != AVL.INTA	&& 
													((AVLNode)$3).type != AVL.CHARA	&& 
													((AVLNode)$3).type != AVL.DECA	&& 
													((AVLNode)$3).type != AVL.BOOLA	&& 
													((AVLNode)$3).type != AVL.INTM	&& 
													((AVLNode)$3).type != AVL.CHARM	&& 
													((AVLNode)$3).type != AVL.DECM  && 
													((AVLNode)$3).type != AVL.BOOLM) { 
														((AVLNode)$$).tcode = ((AVLNode)$1).tcode + ", new AVLBasicType(\"1\", " + ((AVLNode)$3).tcode + ")";
											}
										} else {
											((AVLNode)$$).tcode =  n_exp_list1 + ", " + s_exp1; 
										}

										((AVLNode)$$).type = AVL.LIST;

									}
									;

zero_or_single_expression	:	{ $$ = new AVLNode(""); }
													|	single_expression { $$ = $1; }
													;	

single_expression :	primaryexp 
									{ 
										$$ = $1; 

									}
									| MINUS single_expression %prec NEG 
									{ 
										String s_exp = ((AVLNode)$2).code;
										String s_exp1 = ((AVLNode)$2).tcode;
										$$ = $2;
										((AVLNode)$$).code = "-" + s_exp; 
										((AVLNode)$$).tcode = "-" + s_exp1; 
										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ s_exp + " : cannot perform unary minus on this.");
											numErrors++;
										}

									}
									|	NOT single_expression 
									{ 
										$$ = $2;
										((AVLNode)$$).code = "!" + ((AVLNode)$2).code; 
										((AVLNode)$$).tcode = "!" + ((AVLNode)$2).tcode; 

									}
									|	single_expression INCR
									{ 
										String s_exp = ((AVLNode)$1).code;
										String s_exp1 = ((AVLNode)$1).tcode;
										$$ = $1;
										((AVLNode)$$).code = s_exp + "++ "; 
										((AVLNode)$$).tcode = s_exp + ".set(" + s_exp1 +"+1)";
										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ s_exp + " : cannot perform increment on this.");
											numErrors++;
										}

									}
									|	single_expression DECR
									{ 
										String s_exp = ((AVLNode)$1).code;
										String s_exp1 = ((AVLNode)$1).tcode;
										$$ = $1;
										((AVLNode)$$).code = s_exp + "-- "; 
										((AVLNode)$$).tcode = s_exp + ".set(" + s_exp1 +"-1)";
										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ s_exp + " : cannot perform decrement on this.");
											numErrors++;
										}

									}
									|	single_expression INTO single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;
										$$ = $1;
										((AVLNode)$$).code = exp1 + "*" + exp2;
										((AVLNode)$$).tcode = exp1t + "*" + exp2t;

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in multiplication.");
											numErrors++;
										}
										
										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : cannot perform multiplication on this.");
											numErrors++;
										}
									}
									|	single_expression BY single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;
										$$ = $1;
										((AVLNode)$$).code = exp1 + "/" + exp2; 
										((AVLNode)$$).tcode = exp1t + "/" + exp2t; 

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in division.");
											numErrors++;
										}
										
										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : cannot perform division on this.");
											numErrors++;
										}

									}
									|	single_expression MOD single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + "%" + exp2; 
										((AVLNode)$$).tcode = exp1t + "%" + exp2t; 

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in modulo.");
											numErrors++;
										}
										
										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : cannot perform modulo on this.");
											numErrors++;
										}

									}
									|	single_expression PLUS single_expression
									{
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;
 
										$$ = $1;
										((AVLNode)$$).code = exp1 + "+" + exp2; 
										((AVLNode)$$).tcode = exp1t + "+" + exp2t;

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in addition.");
											numErrors++;
										}
										
										if(!((AVLNode)$$).type.equals(AVL.INT) && ((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp2 + " : cannot perform addition on this.");
											numErrors++;
										}

									}
									|	single_expression MINUS single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + "-" + exp2; 
										((AVLNode)$$).tcode = exp1t + "-" + exp2t;
										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in multiplication.");
											numErrors++;
										}
										
										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : cannot perform multiplication on this.");
											numErrors++;
										}

									}

									|	single_expression LT single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + "<" + exp2; 
										((AVLNode)$$).tcode = exp1t + "<" + exp2t; 

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in < operator.");
											numErrors++;
										}
										
										((AVLNode)$$).type = AVL.BOOL;

									}
									|	single_expression LTE single_expression 
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + "<=" + exp2; 
										((AVLNode)$$).tcode = exp1t + "<=" + exp2t; 

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in <= operator.");
										}
										
										((AVLNode)$$).type = AVL.BOOL;

									}

									|	single_expression GT single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + ">" + exp2; 
										((AVLNode)$$).tcode = exp1t + ">" + exp2t; 

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in > operator.");
											numErrors++;
										}
										
										((AVLNode)$$).type = AVL.BOOL;

									}

									|	single_expression GTE single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + ">=" + exp2; 
										((AVLNode)$$).tcode = exp1t + ">=" + exp2t;

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in >= operator.");
											numErrors++;
										}
										
										((AVLNode)$$).type = AVL.BOOL;

									}
									|	single_expression EQEQ single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).code, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + "==" + exp2; 
										((AVLNode)$$).tcode = exp1t + "==" + exp2t; 

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in == operator.");
											numErrors++;
										}
										
										((AVLNode)$$).type = AVL.BOOL;

									}

									|	single_expression NOTEQ single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + "!=" + exp2; 
										((AVLNode)$$).tcode = exp1t + "!=" + exp2t; 

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in != operator.");
											numErrors++;
										}

										((AVLNode)$$).type = AVL.BOOL;

									}
									|	single_expression OR single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + "||" + exp2; 
										((AVLNode)$$).tcode = exp1t + "||" + exp2t; 

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in || operator.");
											numErrors++;
										}

										if(!((AVLNode)$$).type.equals(AVL.BOOL)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : cannot perform || on non-boolean operands.");
											numErrors++;
										}

									}

									|	single_expression AND single_expression
									{ 
										String exp1 = ((AVLNode)$1).code, exp2 = ((AVLNode)$3).code;
										String exp1t = ((AVLNode)$1).tcode, exp2t = ((AVLNode)$3).tcode;
										Integer t_exp1 = ((AVLNode)$1).type, t_exp2 = ((AVLNode)$3).type;

										$$ = $1;
										((AVLNode)$$).code = exp1 + "&&" + exp2;
										((AVLNode)$$).tcode = exp1t + "&&" + exp2t;

										if(!t_exp1.equals(t_exp2)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : type mismatch in && operator.");
											numErrors++;
										}

										if(!((AVLNode)$$).type.equals(AVL.BOOL)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ exp1 + " : cannot perform && on non-boolean operands.");
											numErrors++;
										}
										
									}
									|	single_expression EQ single_expression
									{ 
										String lval = ((AVLNode)$1).code, exp = ((AVLNode)$3).code;
										String lvalt = ((AVLNode)$1).tcode, expt = ((AVLNode)$3).tcode;
										Integer t_lval = ((AVLNode)$1).type, t_exp = ((AVLNode)$3).type;
										String name = ((AVLNode)$1).name;

										$$ = $1;
										((AVLNode)$$).code = lval + "=" + exp;


										if(((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals("")) {
											((AVLNode)$$).tcode = name + ".set(" + ((AVLNode)$1).index1 + ", " + expt + ")";
										}
										else if(!((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals(""))
											((AVLNode)$$).tcode = name + ".set(" + ((AVLNode)$1).index1 + ", " + ((AVLNode)$1).index2 + ", " + expt + ")";
										else
											((AVLNode)$$).tcode = name + ".set(" + expt + ")";
										if(!t_lval.equals(t_exp)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : type mismatch in = operator.");
											numErrors++;
										}
									
									}
									|	single_expression PLUSEQ single_expression
									{ 
										String lval = ((AVLNode)$1).code, exp = ((AVLNode)$3).code;
										String lvalt = ((AVLNode)$1).tcode, expt = ((AVLNode)$3).tcode;
										Integer t_lval = ((AVLNode)$1).type, t_exp = ((AVLNode)$3).type;
										String name = ((AVLNode)$1).name;

										$$ = $1;
										((AVLNode)$$).code = lval + "+=" + exp; 
										if(((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals("")) {
											((AVLNode)$$).tcode = name + ".set(" + lvalt + ((AVLNode)$1).index1 + ", " + lvalt + " + " + expt + ")";
										}
										else if(!((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals(""))
											((AVLNode)$$).tcode = name + ".set(" + ((AVLNode)$1).index1 + ", " + ((AVLNode)$1).index2 + ", " + lvalt + " + " + expt + ")";
										else
											((AVLNode)$$).tcode = name + ".set(" + lvalt + " - " + expt + ")";

										if(!t_lval.equals(t_exp)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : type mismatch in += operator.");
											numErrors++;
										}

										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : cannot perform += on this.");
											numErrors++;
										}

									}
									|	single_expression MINUSEQ single_expression
									{ 
										String lval = ((AVLNode)$1).code, exp = ((AVLNode)$3).code;
										String lvalt = ((AVLNode)$1).tcode, expt = ((AVLNode)$3).tcode;
										Integer t_lval = ((AVLNode)$1).type, t_exp = ((AVLNode)$3).type;
										String name = ((AVLNode)$1).name;

										$$ = $1;
										((AVLNode)$$).code = lval + "-=" + exp; 
										if(((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals("")) {
											((AVLNode)$$).tcode = name + ".set(" + lvalt + ((AVLNode)$1).index1 + ", " + lvalt + " - (" + expt + ") )";
										}
										else if(!((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals(""))
											((AVLNode)$$).tcode = name + ".set(" + ((AVLNode)$1).index1 + ", " + ((AVLNode)$1).index2 + ", " + lvalt + " - ( " + expt + ") )";
										else
											((AVLNode)$$).tcode = name + ".set(" + lvalt + " - (" + expt + ") )";


										if(!t_lval.equals(t_exp)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : type mismatch in -= operator.");
											numErrors++;
										}

										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : cannot perform -= on this.");
											numErrors++;
										}

									}

									|	single_expression INTOEQ single_expression
									{ 
										String lval = ((AVLNode)$1).code, exp = ((AVLNode)$3).code;
										String lvalt = ((AVLNode)$1).tcode, expt = ((AVLNode)$3).tcode;
										Integer t_lval = ((AVLNode)$1).type, t_exp = ((AVLNode)$3).type;
										String name = ((AVLNode)$1).name;

										$$ = $1;
										((AVLNode)$$).code = lval + "*=" + exp; 
										if(((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals("")) {
											((AVLNode)$$).tcode = name + ".set(" + lvalt + ((AVLNode)$1).index1 + ", " + lvalt + " * (" + expt + ") )";
										}
										else if(!((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals(""))
											((AVLNode)$$).tcode = name + ".set(" + ((AVLNode)$1).index1 + ", " + ((AVLNode)$1).index2 + ", " + lvalt + " * (" + expt + ") )";
										else
											((AVLNode)$$).tcode = name + ".set(" + lvalt + " * (" + expt + ") )";

										if(!t_lval.equals(t_exp)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : type mismatch in *= operator.");
											numErrors++;
										}

										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : cannot perform *= on this.");
											numErrors++;
										}

									}

									|	single_expression BYEQ single_expression
									{ 
										String lval = ((AVLNode)$1).code, exp = ((AVLNode)$3).code;
										String lvalt = ((AVLNode)$1).tcode, expt = ((AVLNode)$3).tcode;
										Integer t_lval = ((AVLNode)$1).type, t_exp = ((AVLNode)$3).type;
										String name = ((AVLNode)$1).name;

										$$ = $1;
										((AVLNode)$$).code = lval + "/=" + exp; 
										if(((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals("")) {
											((AVLNode)$$).tcode = name + ".set(" + lvalt + ((AVLNode)$1).index1 + ", " + lvalt + " /( " + expt + ") )";
										}
										else if(!((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals(""))
											((AVLNode)$$).tcode = name + ".set(" + ((AVLNode)$1).index1 + ", " + ((AVLNode)$1).index2 + ", " + lvalt + " /( " + expt + ") )";
										else
											((AVLNode)$$).tcode = name + ".set(" + lvalt + " /( " + expt + "))";

										if(!t_lval.equals(t_exp)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : type mismatch in /= operator.");
											numErrors++;
										}

										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : cannot perform /= on this.");
											numErrors++;
										}

									}

									|	single_expression MODEQ single_expression
									{ 
										String lval = ((AVLNode)$1).code, exp = ((AVLNode)$3).code;
										String lvalt = ((AVLNode)$1).tcode, expt = ((AVLNode)$3).tcode;
										Integer t_lval = ((AVLNode)$1).type, t_exp = ((AVLNode)$3).type;
										String name = ((AVLNode)$1).name;

										$$ = $1;
										((AVLNode)$$).code = lval + "%=" + exp; 
										if(((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals("")) {
											((AVLNode)$$).tcode = name + ".set(" + lvalt + ((AVLNode)$1).index1 + ", " + lvalt + " %( " + expt + "))";
										}
										else if(!((AVLNode)$1).index2.equals("") && !((AVLNode)$1).index1.equals(""))
											((AVLNode)$$).tcode = name + ".set(" + ((AVLNode)$1).index1 + ", " + ((AVLNode)$1).index2 + ", " + lvalt + " %( " + expt + "))";
										else
											((AVLNode)$$).tcode = name + ".set(" + lvalt + " %( " + expt + "))";

										if(!t_lval.equals(t_exp)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : type mismatch in %= operator.");
											numErrors++;
										}

										if(!((AVLNode)$$).type.equals(AVL.INT) && !((AVLNode)$$).type.equals(AVL.DEC)) {
											System.out.println(fileName+":"+yyline()+": Error at token "+ lval + " : cannot perform %= on this.");
											numErrors++;
										}

									}
									;

primaryexp :	IDENT		
						{ 
							String ident = ((AVLNode)$1).code;

							$$ = $1;
							Integer type = ((AVLNode)$$).type = avlManager.checkVariable(ident);
							if(type == AVL.INT || type == AVL.CHAR || type == AVL.BOOL || type == AVL.DEC)
								((AVLNode)$$).tcode = AVL.getCast(((AVLNode)$$).type) + ((AVLNode)$1).tcode + ".get()";
							else
								((AVLNode)$$).tcode =  ((AVLNode)$1).tcode;
								
							((AVLNode)$$).name = ident;

						}
						|	constant 
						{ 
							$$ = $1;
						}
						|	LP single_expression RP 
						{ 
							$$ = $2;
							((AVLNode)$$).code = "(" +((AVLNode)$2).code + ")"; 
							((AVLNode)$$).tcode = "(" +((AVLNode)$2).tcode + ")"; 
							((AVLNode)$$).type = ((AVLNode)$2).type;

						}
						|	IDENT LP { paramStart = true; } expression_list RP { paramStart = false; paramType = ""; }
						{ 
							String ident = ((AVLNode)$1).code, paramList = ((AVLNode)$4).code;
							String ident1 = ((AVLNode)$1).tcode, paramList1 = ((AVLNode)$4).tcode;
							Integer retType = ((AVLNode)$1).type;
							ArrayList<Integer> fSign = (ArrayList<Integer>)((AVLNode)$4).value;

							retType = avlManager.checkFunction(ident, fSign);
							if(retType == AVL.INV) {
								System.out.println(fileName+":" + yyline() + ": Error at token " + ident + " : Function not declared.");
								numErrors++;
							}
							else {
								((AVLNode)$$).type = avlManager.getFunctionReturnType(ident);
							}
							$$ = $1;
							((AVLNode)$$).code = ident + "(" + paramList + ")"; 							
							((AVLNode)$$).tcode = ident1 + "(" + paramList1 + ")"; 							

						}
						|	SWAP LP expression_list RP 
						{ 
							$$ = $1;
							String paramList = ((AVLNode)$3).code;
							String paramList1 = ((AVLNode)$3).tcode;
							
							Integer retType = ((AVLNode)$1).type;
							ArrayList<Integer> fSign = (ArrayList<Integer>)((AVLNode)$3).value;

							ArrayList<Integer> intArray = new ArrayList<Integer>();
							intArray.add(AVL.INTA);
							intArray.add(AVL.INT);
							intArray.add(AVL.INT);
							ArrayList<Integer> decArray = new ArrayList<Integer>();
							decArray.add(AVL.DECA);
							decArray.add(AVL.INT);
							decArray.add(AVL.INT);
							ArrayList<Integer> charArray = new ArrayList<Integer>();
							charArray.add(AVL.CHARA);
							charArray.add(AVL.INT);
							charArray.add(AVL.INT);
							ArrayList<Integer> boolArray = new ArrayList<Integer>();
							boolArray.add(AVL.BOOLA);
							boolArray.add(AVL.INT);
							boolArray.add(AVL.INT);

							ArrayList<Integer> intMatrix = new ArrayList<Integer>();
							intMatrix.add(AVL.INTM);
							intMatrix.add(AVL.INT);
							intMatrix.add(AVL.INT);
							intMatrix.add(AVL.INT);
							intMatrix.add(AVL.INT);
							ArrayList<Integer> decMatrix = new ArrayList<Integer>();
							decMatrix.add(AVL.DECM);
							decMatrix.add(AVL.INT);
							decMatrix.add(AVL.INT);
							decMatrix.add(AVL.INT);
							decMatrix.add(AVL.INT);
							ArrayList<Integer> charMatrix = new ArrayList<Integer>();
							charMatrix.add(AVL.CHARM);
							charMatrix.add(AVL.INT);
							charMatrix.add(AVL.INT);
							charMatrix.add(AVL.INT);
							charMatrix.add(AVL.INT);
							ArrayList<Integer> boolMatrix = new ArrayList<Integer>();
							boolMatrix.add(AVL.BOOLM);
							boolMatrix.add(AVL.INT);
							boolMatrix.add(AVL.INT);
							boolMatrix.add(AVL.INT);
							boolMatrix.add(AVL.INT);

							if(fSign.size() == 3 && ( fSign.equals(intArray) ||
																				fSign.equals(decArray) ||
																				fSign.equals(boolArray) ||
																				fSign.equals(charArray))) {
								((AVLNode)$$).code = "swap( " + paramList + " )";
								StringTokenizer st = new StringTokenizer(paramList, ",");
								String array = st.nextToken();
								st = new StringTokenizer(paramList1, ",");
								String temp = st.nextToken();
								temp = st.nextToken() + ", " + st.nextToken();
								((AVLNode)$$).tcode = array+".swap( " + temp + " )";
							}
							else if(fSign.size() == 5 && ( fSign.equals(intMatrix) ||
																						 fSign.equals(decMatrix) ||
																						 fSign.equals(boolMatrix) ||
																						 fSign.equals(charMatrix))) {
								((AVLNode)$$).code = "swap( " + paramList + " )";
								StringTokenizer st = new StringTokenizer(paramList, ",");
								String array = st.nextToken();
								st = new StringTokenizer(paramList1, ",");
								String temp = st.nextToken();
								temp = st.nextToken() + ", " + st.nextToken() + ", " + st.nextToken() + ", " + st.nextToken();
								((AVLNode)$$).tcode = array+".swap( " + temp + " )";
							}
							else {
								System.out.println(fileName+":" + yyline() + ": Error at token swap: swap function has wrong format.");
								numErrors++;								
							}
							((AVLNode)$$).type = AVL.VOID;
						}
						| IDENT LSB single_expression RSB 
						{ 
							String ident = ((AVLNode)$1).code, index = ((AVLNode)$3).code;
							String ident1 = ((AVLNode)$1).tcode, index1 = ((AVLNode)$3).tcode;
							Integer t_ident = ((AVLNode)$1).type, t_index = ((AVLNode)$3).type;

							((AVLNode)$$).code = ident + "[" + index + "]"; 
							
							((AVLNode)$$).type = avlManager.checkVariable(ident);

							if(!((AVLNode)$$).type.equals(AVL.INTA) && !((AVLNode)$$).type.equals(AVL.DECA) && !((AVLNode)$$).type.equals(AVL.CHARA)) {
								System.out.println(fileName+":"+yyline()+": Error at token "+ ident + " : expected array type.");
								numErrors++;
							}

							if(!t_index.equals(AVL.INT)) {
								System.out.println(fileName+":"+yyline()+": Error at token "+ ident + " : expected integer type for array index.");
								numErrors++;
							}

							((AVLNode)$$).type = ((AVLNode)$$).type - 1;
							((AVLNode)$$).tcode = AVL.getCast(((AVLNode)$$).type) + ((AVLNode)$1).tcode + ".get(" + ((AVLNode)$3).tcode +")";
							((AVLNode)$$).name = ident;
							((AVLNode)$$).index1 = index1;

						}
						|	IDENT LSB single_expression RSB LSB single_expression RSB 
						{ 
							String ident = ((AVLNode)$1).code, rows = ((AVLNode)$3).code, columns = ((AVLNode)$6).code;
							String ident1 = ((AVLNode)$1).tcode, rows1 = ((AVLNode)$3).tcode, columns1 = ((AVLNode)$6).tcode;
							Integer t_ident = ((AVLNode)$1).type, t_rows = ((AVLNode)$3).type, t_columns = ((AVLNode)$6).type;

							((AVLNode)$$).code = ident + "[" + rows + "]" + "[" + columns + "]";
							((AVLNode)$$).type = avlManager.checkVariable(ident);

							if(!((AVLNode)$$).type.equals(AVL.INTM) && !((AVLNode)$$).type.equals(AVL.DECM) && !((AVLNode)$$).type.equals(AVL.DECM)) {
								System.out.println(fileName+":"+yyline()+": Error at token "+ ident + " : expected matrix type.");
								numErrors++;
							}

							if(!t_rows.equals(AVL.INT) || !t_columns.equals(AVL.INT)) {
								System.out.println(fileName+":"+yyline()+": Error at token "+ ident + " : expected integer type for matrix index.");
								numErrors++;
							}

							((AVLNode)$$).type = ((AVLNode)$$).type - 2;
							((AVLNode)$$).tcode = AVL.getCast(((AVLNode)$$).type) + ((AVLNode)$1).tcode + ".get(" + ((AVLNode)$3).tcode +", "+ ((AVLNode)$6).tcode+ ")";	
							((AVLNode)$$).name = ident;
							((AVLNode)$$).index1 = rows1;
							((AVLNode)$$).index2 = columns1;
						}
						;

constant	:	INTCONST 
					{ 
						$$ = $1; 
						((AVLNode)$$).type = AVL.INT;
					}
					|	DECCONST 
					{ 
						$$ = $1; 
						((AVLNode)$$).type =  AVL.DEC;

					}
					| CHARCONST 
					{	
						$$ = $1;
						((AVLNode)$$).type =  (Integer)AVL.CHAR;
					}
					|	TRUE { $$ = "true"; }
					|	FALSE { $$ = "false"; }
					;

%%
  /* Actually used */
	private Yylex lexer;
	private AVLManager avlManager; 
	private String currentFunction = "";
	private static int numErrors = 0;
	private static int lineno = 0;
	
	/* Not used! */
	private String currentType = "";
	private String paramType = "";
	private boolean funCall = false;
	private boolean showFlag = false;
	private boolean array = false;
	private boolean matrix = false;
	private boolean paramStart = false;
	private int numElements = 0;
	private int countElements = 0;
	private int numRows = 0;
	private int numColumns = 0;
	private int countRows = 0;
	private int countRowElements = 0;
	private int index = 0;
	private boolean main = false;
	private String fileName = "";
	private ArrayList<String> callList;

	private int yyline()
	{
		return lexer.yyline()+1;
	}

	private int yylex () {
    int ret = -1;
    try {
      yylval = new ParserVal(0);
      ret = lexer.yylex();
    }
    catch (Exception e) {
      System.err.println(fileName+":"+yyline()+":"+" I/O error reported while reading token '"+lexer.yytext()+"'.");
    }
    return ret;
  }

  public void yyerror (String error) {
    System.err.println (fileName+":"+yyline()+":"+" syntax error encountered near token '"+ lexer.yytext()+"'.");
  }

  public Parser(Reader r) {
    lexer = new Yylex(r, this);  
		avlManager = new AVLManager();
		avlManager.push();
		showFlag = false;
		array = false;
		matrix = false;
		numElements = 0;
		countElements = 0;
		numRows = 0;
		numColumns = 0;
		countRows = 0;
		countRowElements = 0;
		index = 0;
		currentFunction = "";
		callList = new ArrayList<String>();
}

	public void setFileName(String fName)
	{
		fileName = fName;
	}

  public static void main(String args[]) throws IOException {
		Parser yyparser;

		yyparser = new Parser(new FileReader(args[0]));
		yyparser.setFileName(args[0]);
    yyparser.yyparse();
  }
